package jkcp;

import io.netty.buffer.ByteBuf;

import java.util.LinkedList;
import java.util.Random;

public class LatencySimulator {
	
	  public int current; 
	  public int lostrate, rttmin, rttmax, nmax;
    public DelayTunnel p12;
    public DelayTunnel p21;
    public Random r12;
    public Random r21; 
    
    // lostrate: 往返一周丢包率的百分比，默认 10%
    // rttmin：rtt最小值，默认 60
    // rttmax：rtt最大值，默认 125
    
    public void Init(int lostrate,int rttmin ,int rttmax,int nmax)
    {
		    r12 = new Random();
		    r21 = new Random();
		    p12 = new DelayTunnel();
		    p12.list = new LinkedList<DelayPacket>();
		    p21 = new DelayTunnel();
		    p21.list = new LinkedList<DelayPacket>();
		    current = IkcpTest_h.iclock();
		    lostrate = lostrate / 2;	// 上面数据是往返丢包率，单程除以2
		    rttmin = rttmin / 2;
		    rttmax = rttmax / 2;
		    this.nmax = nmax;
    }
    
    // 发送数据
    // peer - 端点0/1，从0发送，从1接收；从1发送从0接收
    public  int send(int peer,ByteBuf data,int size)
    {
			int rnd = 0;
			if (peer == 0) {
				rnd = r12.nextInt(100);
			} else {
				rnd = r21.nextInt(100);
			}
			// println("!!!!!!!!!!!!!!!!!!!!", rnd, p.lostrate, peer)
			if (rnd < lostrate) {
				return 0;
			}
			DelayPacket pkt = new DelayPacket();
			pkt.Init(size, data);
			current = IkcpTest_h.iclock();
			int delay = rttmin;
			if (rttmax > rttmin) {
				delay += new Random().nextInt() % (rttmax - rttmin);
			}
			pkt.set_ts(current + delay);
			if (peer == 0) {
				p12.list.addLast(pkt);
			} else {
				p21.list.addLast(pkt);
				;
			}
			return 1;
		}
    
    
		public int recv(int peer, ByteBuf data, int maxsize) {
			DelayPacket pkt = null;
			if (peer == 0) {
				if (p21.list.size() == 0) {
					return -1;
				}
				pkt = p21.list.getFirst();
			} else {
				if (p12.list.size() == 0) {
					return -1;
				}
				pkt = p12.list.getFirst();
			}
			current = IkcpTest_h.iclock();
			if (current < pkt.get_ts()) {
				return -2;
			}
			if (maxsize < pkt.get_size()) {
				return -3;
			}
			if (peer == 0) {
				p21.list.removeFirst();
			} else {
				p12.list.removeFirst();
			}
			maxsize = pkt.get_size();
			pkt.get_ptr().markReaderIndex();
			pkt.get_ptr().readBytes(data, maxsize);
			pkt.get_ptr().resetReaderIndex();
			return maxsize;
		}
	}
